from rest_framework import viewsets, status
from rest_framework.response import Response

from user.views import current_user
from .models import Task, Module, Language, TaskUser, Group, GroupUser
from .serializers import TaskSerializer
from django.db.models import Q, Prefetch, Subquery

# 学生中心
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.pagination import PageNumberPagination

from .models import Task
from .serializers import TaskSerializer, TaskUserSerializer

from user.models import User, Clazz
from user.serializers import UserSerializer, ClazzSerializer

from django.db.models import Count
from django.db import transaction

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from task.models import Task, User, TaskUser
from django.db import IntegrityError


# 分页器类
class TaskPagination(PageNumberPagination):
    page_size_query_param = 'page_size'
    max_page_size = 100

    def __init__(self, page_size=10):
        self.page_size = page_size  # 每页显示10条


class SelectTask(viewsets.ReadOnlyModelViewSet):
    """任务查询视图集"""
    serializer_class = TaskSerializer

    def get_queryset(self):

        # 获取当前登录用户的id
        user_id = self.request.user.id

        queryset = Task.objects.select_related('module', 'language', ).only(
            'id', 'completed', 'task_time', 'title',
            'module__name', 'language__name'
        ).filter(users__id=user_id, is_delete=False  # filter根据当前用户进行筛选,筛选出当前的用户下的任务
                 ).prefetch_related(
            Prefetch(
                'taskuser_set',
                queryset=TaskUser.objects.filter(user_id=user_id),
                to_attr='user_taskuser_info'
            )
        )

        params = self.request.query_params
        lang_id = params.get('langName')  # 编程语言（如 'Python'）
        completed = params.get('leave')  # 难易程度（如 '简单题'）
        status = params.get('status')  # 任务状态（如 '未开始'）
        search = params.get('search')  # 新增搜索关键字
        module_name = params.get('module')  # 新增模块名称搜索

        filters = Q()  # 初始空条件
        # 编程语言筛选
        if lang_id:
            filters &= Q(language__id=lang_id)
        # 难易程度筛选
        if completed:
            filters &= Q(completed=completed)
        # 任务状态筛选
        if status:
            if status:
                taskuser_qs = TaskUser.objects.filter(user_id=user_id, status=status).values('task_id')
                queryset = queryset.filter(id__in=Subquery(taskuser_qs))

        if search:
            filters &= Q(title__icontains=search)
        if module_name:
            filters &= Q(module__name__icontains=module_name)

        queryset = queryset.filter(filters)

        return queryset

    def list(self, request, *args, **kwargs):

        queryset = self.get_queryset()

        # 读取前端传过来的分页参数
        page = int(request.query_params.get('page', 1))
        rows = int(request.query_params.get('rows', 20))

        # 计算分页数据
        total_count = queryset.count()
        start = (page - 1) * rows
        end = start + rows
        queryset = queryset[start:end]

        # 序列化数据
        serializer = self.get_serializer(queryset, many=True)

        # 构造响应格式
        data = {
            'total': total_count,
            'results': serializer.data
        }
        return Response(data, status=status.HTTP_200_OK)


class ConditionViewSet(viewsets.ViewSet):
    """获取筛选条件的视图集"""

    def list(self, request):
        # 获取编程语言列表（不变）

        queryset = Language.objects.filter(is_delete=False)

        lang_dict = {
            "name": "编程语言",
            "value": "langName",
            "list": [{"id": lang.pk, "name": lang.name} for lang in queryset]
        }
        level_dict = {
            "name": "难易程度",
            "value": 'leave',
            "list": [
                {"id": "简单题", "name": "简单题"},
                {"id": "中等题", "name": "中等题"},
                {"id": "困难题", "name": "困难题"},
                {"id": "选做题", "name": "选做题"},
            ],
        }

        state_dict = {
            "name": "任务状态",
            "value": 'status',  # 查询条件对应的键
            "list": [
                {"id": 0, "name": "未开始"},
                {"id": 1, "name": "进行中"},
                {"id": 2, "name": "需讲解"},
                {"id": 3, "name": "已提交"},
                {"id": 4, "name": "已检查"},
                {"id": -1, "name": "异常题"},
                {"id": 5, "name": "已完成"},
            ],
        }

        # print(level_dict)

        return Response(data=[lang_dict, level_dict, state_dict])


class TaskViewSet(viewsets.GenericViewSet):
    queryset = Task.objects.filter(is_delete=False)
    serializer_class = TaskSerializer

    def get_permissions(self):
        if self.action in ['create', 'find_clazz_list']:
            return [AllowAny()]
        return super().get_permissions()

    @action(methods=['GET'], detail=False, url_path='current_stu_list', url_name='current_stu_list', )
    def current_stu_list(self, request, *args, **kwargs):
        # 查询 老师id 和 老师信息
        teach_id = request.user.id
        teach = User.objects.get(pk=teach_id)
        teach_serializer = UserSerializer(teach, fields=['name', 'clazz', 'role'])
        clazz_id = teach_serializer.data['clazz']

        # 获取当前班级名
        current_cls = Clazz.objects.filter(id=clazz_id).values('name').first()

        # 找出当前班级学生的 名字、id、邮箱
        students = User.objects.filter(
            clazz_id=clazz_id,
            is_delete=False,
            is_staff=False).values('name', 'id', 'email')

        stu_serializer = UserSerializer(students, many=True, fields=['name', 'id', 'email'])

        result = []
        # 遍历统计 学生 每个任务 状态数量
        for stu in stu_serializer.data:
            status_data = (
                TaskUser.objects
                .filter(user_id=stu.get('id'))
                .select_related('task')
                .values('status')
                .annotate(count=Count(1))
            )
            for statu in list(status_data):
                stat = statu.get('status')
                count = statu.get('count')
                stu[str(stat)] = count
            # 拼接到学生数据中
            result.append(stu)

        current_cls['num_people'] = len(result)
        data = {'clazz': current_cls, 'student': result}

        return Response(data=data, status=status.HTTP_200_OK)

    # 学生中心，获取任务列表
    @action(methods=['GET'], detail=False, url_path='stucent_tasklist', url_name='stucent_tasklist', )
    def stucent_tasklist(self, request, *args, **kwargs):

        keyword = request.query_params.get('search', '').strip()
        lang = request.query_params.get('langName', '').strip()
        module = request.query_params.get('module', '').strip()
        leave = request.query_params.getlist('leave[]')

        # 基础查询
        task_list = Task.objects.filter(is_delete=False).select_related('language', 'module')

        if keyword:
            task_list = task_list.filter(title__icontains=keyword)
        if lang:
            task_list = task_list.filter(language__pk=lang)
        if module and lang:
            task_list = task_list.filter(module__pk=module)
        if leave:
            task_list = task_list.filter(completed__in=leave)

        rows = request.query_params.get("rows", "10")
        # 分页处理
        paginator = TaskPagination(int(rows))
        page = paginator.paginate_queryset(task_list, request)

        results = []
        for task in page:
            results.append({
                'id': task.id,
                'title': task.title,
                'langName': task.language.name if task.language else None,
                'module': task.module.name if task.module else None,
                'leave': task.completed
            })

        # conditionList 构建
        languages = Language.objects.filter(is_delete=False, is_active=True)
        modules = Module.objects.filter(is_delete=False, is_active=True)

        language_list = []
        for lang in languages:
            related_modules = modules.filter(language=lang)
            module_list = [{'id': m.id, 'name': m.name} for m in related_modules]

            language_list.append({
                'id': lang.id,
                'name': lang.name,
                'child': {
                    'name': '任务模块',
                    'value': 'module',
                    'list': module_list
                }
            })

        condition_list = [
            {
                'name': '编程语言',
                'value': 'langName',
                'multi': True,
                'list': language_list
            },
            {
                'name': '难易程度',
                'value': 'leave',
                'multi': True,
                'list': [
                    {'id': '简单题', 'name': '简单题'},
                    {'id': '中等题', 'name': '中等题'},
                    {'id': '困难题', 'name': '困难题'},
                    {'id': '选做题', 'name': '选做题'},
                ]
            }
        ]

        # 拼接最终响应
        paginated_response = paginator.get_paginated_response(results)
        paginated_response.data['conditionList'] = condition_list
        return paginated_response

    @action(methods=['POST'], detail=False, url_path='assign_tasks', url_name='assign_tasks')
    def assign_tasks(self, request, *args, **kwargs):
        """
        分配任务接口（支持单个学生和组内全部学生分配）
        请求数据格式:
        1. 单个学生分配:
        {
            "studentId": 15,
            "taskIds": [2, 22, 23, 24]
        }

        2. 组内全部学生分配:
        {
            "groupId": 1,
            "taskIds": [2, 22, 23, 24]
        }
        """
        try:
            # 获取请求参数
            student_id = request.data.get('studentId')
            group_id = request.data.get('groupId')
            task_ids = request.data.get('taskIds', [])

            # 检查数据有效性
            if not task_ids:
                return Response({'error': 'taskIds不能为空'},
                                status=status.HTTP_400_BAD_REQUEST)

            # 确定是单个学生分配还是组内分配
            if student_id:
                # 单个学生分配模式
                return self._assign_to_single_student(student_id, task_ids)
            elif group_id:
                # 组内全部学生分配模式
                return self._assign_to_group(group_id, task_ids)
            else:
                return Response({'error': '必须提供studentId或groupId'},
                                status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            return Response({'error': str(e)},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def _assign_to_single_student(self, student_id, task_ids):
        """为单个学生分配任务"""
        try:
            # 转换Proxy数组为普通列表（如果需要）
            if hasattr(task_ids, '__iter__') and not isinstance(task_ids, list):
                task_ids = list(task_ids)

            # 获取学生和任务对象
            try:
                student = User.objects.get(pk=student_id)
                tasks = Task.objects.filter(pk__in=task_ids, is_delete=False)

                # 检查学生是否已有这些任务
                existing_tasks = TaskUser.objects.filter(
                    user=student,
                    task_id__in=task_ids
                ).values_list('task_id', flat=True)

                # 只保留未分配的任务ID
                new_task_ids = set(task_ids) - set(existing_tasks)
                tasks = tasks.filter(pk__in=new_task_ids)

            except User.DoesNotExist:
                return Response({'error': '学生不存在'},
                                status=status.HTTP_404_NOT_FOUND)
            except Exception as e:
                return Response({'error': str(e)},
                                status=status.HTTP_400_BAD_REQUEST)

            # 如果没有新任务需要分配
            if not tasks.exists():
                return Response({
                    'success': True,
                    'message': '该学生已经拥有所有指定的任务，无需重复分配'
                }, status=status.HTTP_200_OK)

            # 使用事务确保数据一致性
            with transaction.atomic():
                # 创建新的任务分配
                task_user_objs = [
                    TaskUser(
                        task=task,
                        user=student,
                        status=0  # 默认状态为"未开始"
                    )
                    for task in tasks
                ]

                # 批量创建
                TaskUser.objects.bulk_create(task_user_objs)

            return Response({
                'success': True,
                'message': f'已成功分配{len(tasks)}个任务',
                'assigned_tasks': list(tasks.values_list('id', flat=True)),
                'existing_tasks': list(existing_tasks)
            }, status=status.HTTP_201_CREATED)

        except Exception as e:
            return Response({'error': str(e)},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def _assign_to_group(self, group_id, task_ids):
        """为组内所有学生批量分配任务"""
        try:
            # 检查组是否存在
            try:
                group = Group.objects.get(pk=group_id)
            except Group.DoesNotExist:
                return Response({'error': '组不存在'}, status=status.HTTP_404_NOT_FOUND)

            # 获取组内所有学生ID
            group_students = GroupUser.objects.filter(
                group=group
            ).values_list('user_id', flat=True)

            if not group_students.exists():
                return Response({
                    'success': True,
                    'message': '该组没有学生，无需分配任务'
                }, status=status.HTTP_200_OK)

            # 获取所有任务对象
            try:
                tasks = Task.objects.filter(pk__in=task_ids, is_delete=False)
                if tasks.count() != len(task_ids):
                    invalid_tasks = set(task_ids) - set(tasks.values_list('id', flat=True))
                    return Response({
                        'error': f'以下任务不存在或已被删除: {invalid_tasks}',
                        'valid_tasks': list(tasks.values_list('id', flat=True))
                    }, status=status.HTTP_400_BAD_REQUEST)
            except Exception as e:
                return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

            # 使用事务确保数据一致性
            with transaction.atomic():
                # 为每个学生分配任务
                total_assigned = 0
                student_results = []

                for student_id in group_students:
                    try:
                        student = User.objects.get(pk=student_id)
                    except User.DoesNotExist:
                        student_results.append({
                            'student_id': student_id,
                            'error': '学生不存在',
                            'assigned': 0
                        })
                        continue

                    # 检查学生是否已有这些任务
                    existing_tasks = TaskUser.objects.filter(
                        user=student,
                        task_id__in=task_ids
                    ).values_list('task_id', flat=True)

                    # 只保留未分配的任务ID
                    print(f"Student {student_id} - Existing tasks: {list(existing_tasks)}")  # 打印日志
                    new_task_ids = set(task_ids) - set(existing_tasks)
                    print(f"Student {student_id} - New tasks: {new_task_ids}")  # 打印日志
                    new_tasks = tasks.filter(pk__in=new_task_ids)

                    if not new_tasks.exists():
                        student_results.append({
                            'student_id': student_id,
                            'assigned': 0,
                            'existing': len(existing_tasks),
                            'message': '该学生已经拥有所有指定的任务'
                        })
                        continue

                    # 批量创建任务分配
                    task_user_objs = [
                        TaskUser(
                            task=task,
                            user=student,
                            status=0  # 默认状态为"未开始"
                        )
                        for task in new_tasks
                    ]

                    created = TaskUser.objects.bulk_create(task_user_objs)
                    total_assigned += len(created)

                    student_results.append({
                        'student_id': student_id,
                        'assigned': len(created),
                        'existing': len(existing_tasks),
                        'message': f'成功分配{len(created)}个任务'
                    })

            return Response({
                'success': True,
                'message': f'已为{len(group_students)}名学生分配任务，共分配{total_assigned}个任务',
                'results': student_results,
                'total_assigned': total_assigned,
                'total_students': len(group_students)
            }, status=status.HTTP_201_CREATED)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(methods=['get'], detail=False, url_path='need_explain', url_name='need_explain')
    def need_explain(self, request, *args, **kwargs):

        # 过滤不是本班的学生
        teacher_id = request.user.id
        clazz_id = User.objects.get(pk=teacher_id).clazz_id


        # 查询所有需讲解的任务状态（status=2）
        task_users = TaskUser.objects.filter(status=2).select_related(
            'task__language', 'task__module', 'user'
        )

        # 如果传入了班级ID，则添加班级过滤条件
        if clazz_id:
            task_users = task_users.filter(user__clazz_id=clazz_id)

        task_dict = {}
        for tu in task_users:
            task = tu.task
            if not task:
                continue

            if task.id not in task_dict:
                task_dict[task.id] = {
                    'id': task.id,
                    'title': task.title,
                    'completed': task.completed,
                    'langName': task.language.name if task.language else '',
                    'module': task.module.name if task.module else '',
                    'students': [],
                }

            task_dict[task.id]['students'].append({
                'id': tu.user.id,
                'name': tu.user.name,
                'type': 'info',  # 可根据用户角色/状态设置标签颜色等
                'color': '',  # 前端调用 getRandomColor() 设置
            })

        return Response(list(task_dict.values()), status=status.HTTP_200_OK)

    @action(methods=['PUT'], detail=False, url_path='reset_task', url_name='reset_task')
    def reset_task(self, request, *args, **kwargs):
        task_id = request.data.get('task_id')
        student_ids = request.data.get('student_ids')

        if not task_id or not isinstance(student_ids, list):
            return Response({'message': '参数不正确'}, status=status.HTTP_400_BAD_REQUEST)

        # 批量更新任务状态
        updated_count = TaskUser.objects.filter(
            task_id=task_id,
            user_id__in=student_ids,
            status=2  # 只重置“需讲解”的
        ).update(status=0)

        return Response({'message': f'成功重置了 {updated_count} 个任务记录'}, status=status.HTTP_200_OK)


# 任务代码提交和修改，保存接口
class SaveCodeViewSet(viewsets.ViewSet):
    """
    保存代码的视图集
    """

    def create(self, request):
        # 获取当前用户id，改id直接从浏览器上获取
        user_id = self.request.user.id
        # 下面的数据从前端返回的数据中取出
        task_id = request.data.get('task_id')
        code = request.data.get('code')
        checked = request.data.get('checked', False)

        try:
            task_user = TaskUser.objects.get(task_id=task_id, user_id=user_id)
            task_user.answer = code
            # 如何勾选不会做，此时checked为true，即表明需讲解
            if checked:
                task_user.status = 2
            # 如果没有勾选，则是直接保存，则表明已提交
            else:
                task_user.status = 3
            task_user.save()
            return Response({'message': '保存成功'}, status=status.HTTP_200_OK)
        except TaskUser.DoesNotExist:
            return Response({'error': '任务不存在'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)


# 开始,已完成视图函数
class StartEndTaskViewSet(viewsets.ViewSet):
    """开始按钮，完成按钮视图函数"""

    def create(self, request):
        # 获取当前用户id，改id直接从浏览器上获取
        user_id = self.request.user.id
        # 下面的数据从前端返回的数据中取出
        task_id = request.data.get('id')
        state = request.data.get('status')

        try:
            task_user = TaskUser.objects.get(task_id=task_id, user_id=user_id)
            # 如何勾选不会做，此时checked为true，即表明需讲解
            if state == 0:
                task_user.status = 1
            # 如果没有勾选，则是直接保存，则表明已提交
            if state == 4:
                task_user.status = 5
            task_user.save()
            return Response({'message': '保存成功'}, status=status.HTTP_200_OK)
        except TaskUser.DoesNotExist:
            return Response({'error': '任务不存在'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)


# 教师端检查按钮
class TeacherCheckButtonViewSet(viewsets.ViewSet):
    """任务查询视图集（只查任务表）"""
    @action(methods=['GET'], detail=False, url_path='teacher-task-answers')
    def teacher_task_answers(self, request):
        # 获取当前老师的id
        user_id = self.request.user.id
        # 获取当前任务的id
        task_id = request.query_params.get('task_id')
        print("task_id", task_id)

        # 获取当前老师的clazz_id
        teacher = User.objects.filter(id=user_id, is_delete=False).first()
        if not teacher:
            return Response({"detail": "教师不存在"}, status=404)
        clazz_id = teacher.clazz_id

        if not clazz_id:
            return Response({"detail": "教师未分配班级"}, status=400)

        # 找到该班级下的所有学生
        students_qs = User.objects.filter(
            clazz_id=clazz_id,
            is_staff=0,
            is_delete=False
        )
        student_ids = students_qs.values_list('id', flat=True)

        # 关联 task_user 表查到该学生的答案
        task_user_qs = TaskUser.objects.filter(
            user_id__in=student_ids,
            status=3,
            task_id=task_id,
        ).select_related('user', 'task').order_by('id')

        # 组装数据
        results = []
        for item in task_user_qs:
            results.append({
                "student_id": item.user.id,
                "student_name": item.user.name,
                "answer": item.answer,
            })
        print(results)

        return Response({"results": results})


class AssignTaskViewSet(viewsets.ViewSet):
    def create(self, request):
        print("=== AssignTaskView 入参：", request.data)
        task_id = request.data.get('task_id')
        user_ids = request.data.get('user_ids')

        if not task_id or not user_ids:
            return Response({'msg': '参数不完整'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            task = Task.objects.get(id=task_id)
        except Task.DoesNotExist:
            return Response({'msg': '任务不存在'}, status=status.HTTP_404_NOT_FOUND)

        success_count = 0
        for user_id in user_ids:
            try:
                user = User.objects.get(id=user_id)
                # 创建 TaskUser 记录，防止重复分配
                TaskUser.objects.get_or_create(task=task, user=user)
                success_count += 1
            except User.DoesNotExist:
                continue
            except IntegrityError:
                continue  # 避免 unique_together 冲突

        return Response({
            'msg': f'成功分配 {success_count} 人员',
            'success_count': success_count
        }, status=status.HTTP_200_OK)

    @action(methods=['post'], detail=False)
    def get_assigned_users(self, request):
        print('request.body:', request.body)  # 原始请求体（bytes）
        print('request.data:', request.data)
        task_id = request.data.get('task_id')
        if not task_id:
            return Response({'msg': 'task_id缺失'}, status=400)

        users = User.objects.filter(taskuser__task_id=task_id)
        data = [{'id': user.id, 'name': user.username} for user in users]
        return Response(data)